#!/usr/bin/env ruby

require 'socket'
require 'base64'

gem 'base32'
require 'base32'

gem 'pNet-DNS'
require 'Net/DNS'

PORT=4000
BIND_ADDR="127.0.0.1"
MAX_PACKET_SIZE=8192
DOMAIN_NAME="tun.ni.ac.nz"
NAMESERVER="127.0.0.1"
POLLER_SLEEP=2

@client_addr = nil
@client_port = nil

sock = UDPSocket.new
sock.bind BIND_ADDR, PORT

Thread.new do
  send_resolver = Net::DNS::Resolver.new
  send_resolver.nameservers = [NAMESERVER]

  puts "dnstunc now listening on %s:%s (UDP)" % [BIND_ADDR, PORT]

  while true
    buf = sock.recvfrom(MAX_PACKET_SIZE)
    @client_addr = buf[1][3]
    @client_port = buf[1][1]

    hostname = Base32.encode(buf[0]).downcase! + '.data.' + DOMAIN_NAME

    puts "looking up %s" % hostname
    send_resolver.query hostname, "TXT"
  end
end

Thread.new do
  recv_resolver = Net::DNS::Resolver.new
  recv_resolver.nameservers = [NAMESERVER]

  seq = 0
  while true
    puts "PING"
    response = recv_resolver.query("%i.ping.%s" % [seq, DOMAIN_NAME])
   
    if response && response.answer
      response.answer.select { |rr| rr.class == Net::DNS::RR::TXT }.each do |txt|
        data = Base64.decode64 txt.txtdata
        puts "PONG: %s" % data

        sleep 0.1 while !@client_addr || !@client_port
        sock.send data, 0, @client_addr, @client_port
      end
    end

    seq += 1
    sleep(POLLER_SLEEP)
  end
end

sleep 60 while true
